package classification;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import features.FeaturesReduction;

import stemmer.porter.SnowballStemmer;
import utilities.DCUtilities;
import utilities.Logger;

import model.Category;
import model.Document;
import model.Term;

public class TestSetReader {
	private HashMap<String, Term> dictionary;
	private ArrayList<Document> documents;
	private HashMap<String, Category> categories;
	
	
	public TestSetReader(HashMap<String, Term> dictionary, HashMap<String, Category> categories){
		this.dictionary = dictionary;
		this.categories = categories;
		this.documents = new ArrayList<Document>();
	}
	
	public void read(String testSetPath) throws Exception{
		File dir;
		dir = new File(testSetPath);
		if(dir.isDirectory()) {
			for(int i=0;i<dir.listFiles().length;i++) {
				readFile(dir.listFiles()[i]);
			}
		}
		else {
			throw new Exception("IS NOT A DIRECTORY!");
		}
		
		Logger.logln("Reading test set finished!");
	}
	
	private void readFile(File file) throws DocumentException{
		SAXReader reader = new SAXReader();
		org.dom4j.Document document = reader.read(file);
		
		Element root = document.getRootElement();
		
		List articles = root.elements();
		
		Iterator iter = articles.iterator();
		
		while(iter.hasNext()) {
			
			Element article = (Element)iter.next();
			String id = article.attributeValue(DCUtilities.DOC_ID_TAG);
			
			Element text = article.element(DCUtilities.DOC_TEXT_TAG);
			
			
			Document doc = new Document(Integer.parseInt(id));
			
			if (!readCategories(doc,article)){
				continue;
			}
			
			if(text != null) {
				String title = text.elementText(DCUtilities.DOC_TITLE_TAG);
				
				if (!DCUtilities.READ_NO_TITLE && FeaturesReduction.hasNoTitle(title)){
					continue;
				}
				
				
				String body = text.elementText(DCUtilities.DOC_BODY_TAG);
				try {
					stemming(doc,body,DCUtilities.BODY_TERM_TYPE);
					stemming(doc,title,DCUtilities.TITLE_TERM_TYPE);
				}
				catch(Throwable t) {
					Logger.logln("BODY STEMMING ERROR!");
					t.printStackTrace();
				}
			}
			documents.add(doc);
		}
	}
	
	private boolean readCategories(Document doc,Element article){
		boolean flag = false;
		Element categories = article.element(DCUtilities.CATEGORIES_TAG);
		
		List categoriesList = categories.elements();
		
		Iterator iter = categoriesList.iterator();
		
		while (iter.hasNext()){
			
			Element category = (Element)iter.next();
			String categoryName = category.getText();
			
			Category temp = this.categories.get(categoryName);
			
			if (temp != null){
				flag = true;
				doc.addCategory(temp);
			}
		}
		return flag;
	}
	
	private void stemming(Document doc,String bodyOrTitle, int textType) throws Throwable{
		
		if(bodyOrTitle == null)
			return;
		
		Class stemClass = Class.forName(DCUtilities.STEMMER_CLASS);
        SnowballStemmer stemmer = (SnowballStemmer) stemClass.newInstance();
        
        StringTokenizer st = new StringTokenizer(bodyOrTitle,DCUtilities.STRING_DELIMITERS);
        
        String input;
        
        Term term = null;

        while(st.hasMoreTokens()) {
        	input = st.nextToken();
     	
	       	if (input.length()>1) {
	       		input = input.toLowerCase();
	       		stemmer.setCurrent(input);
	       		stemmer.stem();
	       	
	       		term = dictionary.get(stemmer.getCurrent());
	       		if (term != null){
	       			doc.addTerm(term, textType);
	       		}
	        }
        }
	}
	
	public ArrayList<Document> getDocuments() {
		return documents;
	}
}
